﻿// Decompiled with JetBrains decompiler
// Type: Netick.RpcManager
// Assembly: Netick, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
// MVID: 6726ECA1-C773-4CF7-8952-E81B30D93B52
// Assembly location: D:\WorkSpaceDemo\UPM\NetickForUnity\Netick\Runtime\Netick.dll
// XML documentation location: D:\WorkSpaceDemo\UPM\NetickForUnity\Netick\Runtime\Netick.xml

using System;
using System.Collections.Generic;
using System.Reflection;

#nullable disable
namespace Netick;

internal class RpcManager
{
  internal NetickEngine Engine;
  internal Dictionary<int, int> RPC_HashToIndex = new Dictionary<int, int>(1024 /*0x0400*/);
  internal int[] RPC_IndexToHash;
  internal List<Action<NetickEngine, INetickNetworkScript, RpcContext, NetworkPlayerId, IntPtr>> RPC_IndexToHandler = new List<Action<NetickEngine, INetickNetworkScript, RpcContext, NetworkPlayerId, IntPtr>>(1024 /*0x0400*/);
  internal RpcDefinitionInfo[] RpcIdToDefinitionInfo;
  internal int CurrentRpcId = -1;
  internal List<NetworkRpc> RelatedStaticRPCs = new List<NetworkRpc>(1024 /*0x0400*/);
  internal FastAllocator RpcAllocator;
  private Queue<NetworkRpc> Free = new Queue<NetworkRpc>(1024 /*0x0400*/);

  public RpcManager(NetickEngine engine)
  {
    this.Engine = engine;
    for (int index = 0; index < 512 /*0x0200*/; ++index)
      this.Free.Enqueue(this.Create());
    this.RpcAllocator = new FastAllocator(131072L /*0x020000*/);
    this.Init();
  }

  public void Reset()
  {
    for (int index = 0; index < this.RelatedStaticRPCs.Count; ++index)
      this.RelatedStaticRPCs[index].IsValid = false;
    this.RelatedStaticRPCs.Clear();
  }

  private void Init()
  {
    int index = 0;
    this.RpcIdToDefinitionInfo = new RpcDefinitionInfo[this.Engine._reflectionData.RpcMethods.Count];
    this.RPC_IndexToHash = new int[this.Engine._reflectionData.RpcMethods.Count];
    foreach (KeyValuePair<MethodInfo, MethodInfo> rpcMethod in this.Engine._reflectionData.RpcMethods)
    {
      int stableHashCode = NetickUtils.GetMethodName(rpcMethod.Value).GetStableHashCode();
      Action<NetickEngine, INetickNetworkScript, RpcContext, NetworkPlayerId, IntPtr> action = (Action<NetickEngine, INetickNetworkScript, RpcContext, NetworkPlayerId, IntPtr>) Delegate.CreateDelegate(typeof (Action<,,,,>).MakeGenericType(typeof (NetickEngine), typeof (INetickNetworkScript), typeof (RpcContext), typeof (NetworkPlayerId), typeof (IntPtr)), rpcMethod.Key);
      InternalNetworkRpcInfo customAttribute1 = (InternalNetworkRpcInfo) rpcMethod.Value.GetCustomAttributes(typeof (InternalNetworkRpcInfo), true)[0];
      Rpc customAttribute2 = (Rpc) rpcMethod.Value.GetCustomAttributes(typeof (Rpc), true)[0];
      this.RPC_IndexToHash[index] = stableHashCode;
      this.RPC_HashToIndex.Add(stableHashCode, index);
      this.RPC_IndexToHandler.Add(action);
      this.RpcIdToDefinitionInfo[index] = new RpcDefinitionInfo(customAttribute1.Size, customAttribute1.IsTargeted, customAttribute1.IsStatic, customAttribute2.IsReliable, customAttribute2.Source, customAttribute2.Target);
      ++index;
    }
  }

  private NetworkRpc Create()
  {
    return new NetworkRpc(this, this.Engine.IsServer ? this.Engine.MaxClients : 1);
  }

  public NetworkRpc Get(
    int id,
    INetickNetworkScript behaviour,
    bool isReliable,
    RpcPeers target,
    bool isTargeted,
    NetworkPlayerId sourcePlayer,
    NetworkPlayerId targetPlayer,
    int sizeWords)
  {
    if (sizeWords * 8 > this.Engine.Config.MaxDataPerConnectionPerTickInBytes - 100)
    {
      NetickLogger.LogError(this.Engine, (object) $"Rpc size [{sizeWords * 8}] is too big! Max size is {this.Engine.Config.MaxDataPerConnectionPerTickInBytes - 100} bytes. This can be changed by increasing MaxSendableDataSize in Netick Settings. However, it's not recommended and using the data sending API is preferred for sending large amounts of data. Please read the docs.");
      return (NetworkRpc) null;
    }
    return this.Free.Count < 1 ? this.Create().Init(id, behaviour, isReliable, target, isTargeted, sourcePlayer, targetPlayer, sizeWords) : this.Free.Dequeue().Init(id, behaviour, isReliable, target, isTargeted, sourcePlayer, targetPlayer, sizeWords);
  }

  public unsafe void Push(NetworkRpc rpc)
  {
    this.RpcAllocator.Free((void*) rpc.Data, rpc.SizeWords * 4);
    if (!this.Free.Contains(rpc))
      this.Free.Enqueue(rpc);
    else
      NetickLogger.LogError(this.Engine, (object) "rpc error");
  }
}
